// Album class
var Album = new Class({
	info: {
		id: 0, 
		primary: 0, 
		secret: '', 
		server: 0, 
		farm: 0,
		tags: '', 
		title: '',
		description: ''
	},  // end info{}
	
	initialize: function(json, root, fade_duration) {
		$extend(this.info, json);
		// initialize vars
		this.photos = {};
		this.prev_id = '';
		this.currentphoto = null;
		this.root = root || '/photos/';
		// windows, it seems, does not support proper scaling of images
		this.sizesuffix = (window.win) ? '' : 'b';
		// set fade duration for Darkbox
		if (!fade_duration) fade_duration = 500;
		this.fade_duration = fade_duration;
		
		this.history = HistoryManager.register(
			'main',
			[0],
			function(args) { this.view(args[0]); }.bind(this),
			false,
			false
		);
			
		// cycle through photos
		var output = [];
		var prevPhotoId = false;
		var shiftdown = 0;
		var total = 0;
		json.photo.each(function(photo) {
			var photoObj = new Photo(photo, prevPhotoId);
			// set "next" photo.. for the previous one
			if (prevPhotoId) (this.photos[prevPhotoId]).setNext(photoObj.uniqueId());
			// add this photo to album collection
			this.photos[photoObj.uniqueId()] = photoObj; 
			
			prevPhotoId = photoObj.uniqueId();
			total++;
		}, this);
		
		this.total = total;

		// set up album page
		$('titlename').setHTML(this.info.title);
		$('albumnumber').setHTML(['(', this.total, ')'].join(''));

		// set photo controls
		['prev', 'next'].each(function(control) {
			var button = $('hud-' + control);
			button.addEvent('click', function(e) {
				new Event(e).stop();
				if (!button.hasClass('disabled')) this.view(button.getProperty('href'));
			}.bind(this));
		}, this);
		// do nothing when hud is clicked on
		$('hud').addEvent('click', function(e) { new Event(e).stop(); });
		
		// add functionality to block elements
		var wrapper = null, img = null, caption = null, photo = null, shiftdown = 0, captionwidth = 0, trunc = 0;
		$$('.block').each(function(block) {
			wrapper = block.getLast();
			img = wrapper.getFirst();
			caption = block.getFirst();
			photo = this.photos[block.id.substr(2)];
			
			// calculate px to shift: photoObj.sizes[1][1] = height of small-sized img
			shiftdown = 240 - photo.sizes[1][1]; 
			captionwidth = photo.sizes[1][0] - 5;
			wrapper.setStyle('top', shiftdown);
			caption.setStyle('width', captionwidth);
			// margins.setSize(block);
			
			trunc = Math.ceil(photo.sizes[1][0] / 6);
			if (caption.hasClass('desc')) trunc -= 3;	// take into account comment-bubble
			caption.setHTML(photo.getTitle(true).truncate(trunc));
			
			block.addEvents({
				'click': function() { this.darkboxIt(block.id.substr(2)); }.bind(this),
				'mouseover': function() { block.addClass('hover'); },
				'mouseout': function() { block.removeClass('hover'); }
			});

		}, this);

		// initialize Darkbox
		this.darkbox = new Darkbox('mainphoto', '', {
			outside_opacity: 0.95,
			outside_click: false,
			set_position: false,
			fade_duration: this.fade_duration
		});
		['darkbox_overlay', 'mainphoto'].each(function(item) {
			$(item).onclick = this.darkboxIt.bind(this);
			$(item).addClass('clickable');
		}, this);
		$('darkbox_overlay').setStyles({
			width: screen.width,
			height: screen.height
		});
		// remove clicking functionality (darkbox) from centerpiece
		$('centerpiece').addEvent('click', function(e) { new Event(e).stop(); });
		$('centerpiece').addClass('notclickable');
	},  // end initialize()
	
	// resize main photo & set position
	resize: function(photo) {
		// get correct sizes
		var img = $('centerpiece').getFirst();
		var sizes = photo.getNewSizes(img, this.getSizeIndex());
		
		// set sizes
		img.setProperties(sizes);
		$('centerpiece').style.height = sizes['height'] + 'px';
		['centerpiece', 'h-title', 'h-description'].each(function(node) {
			$(node).style.width = sizes['width'] + 'px';
		});
		
		// set positions
		var shiftleft = (window.ie) ? 0 : Math.floor((window.getWidth() - sizes['width'] - 40) / 2);
		$('mainphoto').setStyles({
			'top': Math.floor(window.getHeight() / 50),
			'left': shiftleft
		});
	},  // end resize()
	
	darkboxIt: function(id) {
		// main photo: turn on darkbox
		if ($('b-' + id)) {
			this.darkbox.open();
		}
		// grid: turn off darkbox
		else {
			this.darkbox.close();
		}

		this.view(id);
	},  // end darboxIt()
	
	// type: 'grid', 'hybrid' (not yet), 'photo'
	// id: photo unique id or 0
	view: function(id) {
		var url = this.root + this.info.id + '/';
		// show main photo
		if ($('b-' + id)) {
			this.prev_id = id;
			$('container').setStyle('overflow', 'hidden');
			this.currentphoto = this.photos[id];
			this.setCenterpiece();
			if (!$('mainphoto').visible()) {
				this.darkbox.open();
			}
			url += id;
		}
		// show grid
		else {
			id = [0];		// id = 0 regardless
			$('container').setStyle('overflow', 'auto');
			if ($('mainphoto').visible()) {
				this.darkbox.close();
			}
		}
		this.history.setValue(0, id);
		mookit.analytics(url);
	},  // end view()
	
	// updates centerpiece image and sets controls
	// precondition: this.currentphoto must be up-to-date
	setCenterpiece: function() {
		var current = this.currentphoto;
		var index = this.getSizeIndex();
		
		$('centerpiece').setHTML(current.buildImg(this.sizesuffix));
		this.resize(current);
		var size = ['<div class="size">', current.sizes[index][0], ' x ', current.sizes[index][1], '</div>'].join('');
		$('h-title').setHTML(size + current.getTitle(true));
		$('h-description').setHTML(current.description);
		// set href attributes
		$('hud-next').setProperty('href', current.getNext() || '#');
		$('hud-prev').setProperty('href', current.getPrev() || '#');
		// set additional functionality
		['prev', 'next'].each(function(control) {
			var button = $('hud-' + control);
			if (button.getProperty('href') == '#') button.addClass('disabled');
			else button.removeClass('disabled');
		}, this);
	},  // end setCenterpiece()
	
	// return size index for current photo based on this.sizesuffix
	// this can get tricky! sometimes 'o' has an index of 3, not 4!
	getSizeIndex: function() {
		var index = 0;
		
		switch (this.sizesuffix) {
		case 't':
			break;
		case 'm':
			index = 1;
			break;
		case 'b':
			index = 3;
			// if sizes[4] is empty, image is too small -- 'b' option does not exist in such a case
			if (!this.currentphoto.sizes[4][0]) this.sizesuffix = 'o';
			break;
		case 'o':
			index = (this.currentphoto.sizes[4][0]) ? 4 : 3;	// just to be safe
			break;
		case '':
		default:
			index = 2;
		}

		return index;
	}  // end getSizeIndex()
});  // end Album

var Photo = new Class({
	ignorelist: ['dsc_', "\\.jpg"],		// for testing regexp in getTitle()
	
	info: {
		id: 0,
		secret: '',
		server: 0,
		farm: 0,
		title: '',
		description: '',
		originalsecret: '',
		originalformat: '',
		tags: '',
		datetaken: '',
		sizes: []
	},  // end info{}
	
	// prev: false (if none) or previous Photo object unique id
	initialize: function(json_photo, prev) {
		$extend(this.info, json_photo);
		$H(this.info).each(function(value, key) {
			this[key] = value;
		}, this);
		
		this.setNext(false);
		this.setPrev(prev);
	},  // end initialize()
	
	// reflect: bool. If true, show a reflection. Default false.
	buildImg: function(size) {
		return ['<img src="', this.getUrl(size), '">'].join('');
	},  // end buildImg()
	
	uniqueId: function(isoriginal) {
		var secret = (isoriginal) ? this.originalsecret : this.secret;
		return [this.id, '_', secret].join('');
	},  // end uniqueId()
	
	// size: s, t, m, '' (default), b, o
	getUrl: function(size) {
		// temp return (NEED TO USE FARM, SECRET, ETC)
		var newsize = '';
		var url = ['http://farm', this.farm, '.static.flickr.com/', this.server, '/'];
		
		if (size != '') newsize = ['_', size].join('');
		if (size == 'o') url.extend([this.uniqueId(true), newsize, '.', this.originalformat]);
		else url.extend([this.uniqueId(), newsize, '.jpg']);
		
		return url.join('');
	},  // end getUrl()
	
	// displayFilename: bool. If false (default), will not return titles with .jpg extension
	getTitle: function(displayFilename) {
		var title = this.title;
		if (!displayFilename && title.test(this.ignorelist.join('|'), 'i')) return '';
		return title;
	},  // end getTitle()
	
	// on resize (for main photo), calculate new sizes
	getNewSizes: function(img, index) {
		if (!index) index = 3;
		var bufferheight = $('hud').offsetHeight + 36;
		// sizes[3]: "large" format, or original format if sizes[4] is empty
		// w & h are constants: once set, they should never change
		var w = newwidth = this.sizes[index][0];
		var h = newheight = this.sizes[index][1];
		
		var maxheight = Window.getHeight() - 220;
		var maxwidth = Window.getWidth() - 170;
		
		// TODO: need to set minimum
		// TODO: need to take control height (or other elements) into account
		if (newwidth > maxwidth) {
			newwidth = maxwidth;
			newheight = Math.ceil((h / w) * maxwidth);
		}
		// NOT elseif
		if (newheight > maxheight) {
			newheight = maxheight;
			newwidth = Math.ceil((w / h) * maxheight);
		}
		
		return {
			'width': newwidth,
			'height': newheight					
		};
	}, // end getNewSizes()

	getPrev: function() {
		return this.prev;
	},
	getNext: function() {
		return this.next;
	},
	// param: false (if none) or prev/next Photo object unique id
	setPrev: function(photo_id) {
		this.prev = photo_id;
	},  // end setPrev()
	setNext: function(photo_id) {
		this.next = photo_id;
	}  // end setNext()
});  // end Photo

var AlbumsList = new Class({
	options: {
		title: 'Web Gallery',
		currenttag: '',
		taglist: '',
		friendlyurl: true,
		galleryurl: '/gallery/'
	},  // end options{}
	
	initialize: function(options) {
		$extend(this.options, options);
		this.currenttag = this.defaulttag = this.options.currenttag;
		
		// set title
		$('titlename').setHTML(this.options.title);
		
		// modify tagbar and tags
		if ($('tagbar')) {
			var tagwidth = 0;
			var extrasize = (window.ie6) ? 34 : 30;
			$$('#tagbar li').each(function(tag) {
				tagwidth += tag.getSize().size.x + extrasize;
				tag.getFirst().addEvent('click', function(e) {
					new Event(e).stop();
					this.filterTag(tag.getFirst().getProperty('href').substr(1));
				}.bind(this));
			}, this);
			$('tagbar').setStyle('width', tagwidth);
			
			this.history = HistoryManager.register(
				'tag',
				[0],
				function(args) { this.filterTag(args[0]); }.bind(this),
				false,
				false
			);

		}
		
		// set album params
		var photonum = '', num = 0;
		$$('.albumblock').each(function(album) {
			// pluralize photos
			photonum = album.getChildren()[1];
			num = photonum.getText();
			photonum.setHTML('photo'.pluralize(num, true));
			// margins.setSize(album);
			
			// add events
			album.addEvents({
				'click': function() { this.linkTo(album.id.substr(2)); }.bind(this),
				'mouseover': function() { album.addClass('hover'); },
				'mouseout': function() { album.removeClass('hover'); }
			});
		}, this);
		
	},  // end initialize()
	
	// prereq: album_id should always be set
	linkTo: function(album_id) {
		var url = '';
		if (this.options.friendlyurl) {
			url = [this.options.galleryurl, this.currenttag, '/album/', album_id];
		}
		else {
			url = ['index.php?album=', album_id, '&tag=', this.currenttag];
			if (this.currenttag) url.extend(['#tag-', this.currenttag]);
		}
		location.href = url.join('');
	},  // end linkTo()
	
	filterTag: function(tag) {
		if (!tag) tag = this.defaulttag;
		
		$('t-' + this.currenttag).removeClass('active');
		$('t-' + tag).addClass('active');
		
		$$('.albumblock').each(function(album) {
			if (album.hasClass(tag)) album.show();
			else album.hide();
		});
		
		this.currenttag = tag;
		this.history.setValue(0, tag);
	}  // end filterTag()
});  // end AlbumsList

/* global fn() */
var Margins = new Class({
	initialize: function(type) {
		if (type == 'showphotos') {
			this.classname = '.block';
			this.blocksize = 250;
		}
		else {
			this.classname = '.albumblock';
			this.blocksize = 168;
		}
		
		this.marginsize = this.getSize();
	},
	
	getSize: function() {
		var blocksperrow = Math.floor(($('container').getSize().scrollSize.x - 10) / this.blocksize);
		var mod = ($('container').getSize().scrollSize.x - 10) % this.blocksize;
		return Math.floor(mod / blocksperrow) - 1;
	},

	setSize: function(element) {
		element.setStyle('margin-right', this.marginsize);
	},

	resizeAll: function() {
		this.marginsize = this.getSize();
		
		$$(this.classname).each(function(block) {
			this.setSize(block);
		}, this);
	}
});


